home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
lang
/
mc302
/
dosutil
/
tfb.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-18
|
11KB
|
496 lines
/*
* A TSR file browser
*
* Copyright 1993-1994 Dave Dunfield
* All rights reserved.
*
* Permission granted for personal (non-commercial) use only.
*
* Compile command: cc tfb -fop
*/
#include <stdio.h>
#include <window.h>
#include <tsr.h>
#define SCREEN_SIZE 80 /* Width of screen */
#define LINE_SIZE 250 /* Maximum width of input line */
#define NUM_TAGS 10 /* Maximum number of tag locations */
#define NUM_FILES 10 /* Maximum number of pick files */
int tab_size = 8, line, lcount, offset, tag, file, fnext = 0,
file_info[NUM_FILES][NUM_TAGS+4], Msel, Mval[NUM_FILES];
unsigned sizeh, sizel, maxline, lines[2048][2], tags[NUM_TAGS];
char filename[NUM_FILES][51], search_string[NUM_FILES][51], *Mptr[NUM_FILES+1],
*argptr = 0;
struct WINDOW *mwin;
FILE *fp = 0;
/* Window video attributes */
int attrs[] = {
WSAVE|WCOPEN|0x70, /* 0: Message window */
WSAVE|WCOPEN|0x07, /* 1: Main screen */
WSAVE|WBOX1|WCOPEN|0x70 /* 2: Info entry */
};
/* Form for entering filename */
char *form1[] = {
64<<8|3,
"\x00\x00\x32Filename:",
0 };
/* Form for setting tab size */
char *form2[] = {
30<<8|3,
"\x00\x00\x85Tab size:",
0 };
/* Form for selecting line number */
char *form3[] = {
30<<8|3,
"\x00\x00\x85Line number:",
0 };
/* Form for string searches */
char *form4[] = {
64<<8|3,
"\x00\x00\x32Search for:",
0 };
/* Welcome message */
char hello[] =
"TFB [/ACLRS] [file] - Copyright 1993-1994 Dave Dunfield. All rights reserved.";
/*
* Main file browser program
*/
browser()
{
int i, x;
char buffer[LINE_SIZE+1];
mwin = wopen(0, 0, 80, 1, attrs[0]);
wputs(hello);
wopen(0, 1, 80, 24, attrs[1]);
wcursor_off();
/* If file already active... reopen */
if(fnext) {
if(!(fp = fopen(filename[file], "rb")))
fnext = 0; }
/* If no file open... prompt for one. */
if(!fnext) {
*buffer = 0;
do {
if(argptr) {
strcpy(buffer, argptr);
argptr = 0; }
else if(wform(7, 10, attrs[2], form1, buffer))
*buffer = 0;
if(!*buffer) {
wclose();
wclose();
return; } }
while(!open_file(buffer));
strcpy(filename[file = fnext++], buffer); }
/* Display screen from file */
display:
if(line > (lcount - 23)) line = lcount - 23;
if(line < 0) line = 0;
if(offset < 0) offset = 0;
update_status();
gotoline(line);
for(i=0; i < 24; ++i) {
wgotoxy(0, i);
if(fgets(buffer, sizeof(buffer)-1, fp))
display_line(buffer);
if((line + i) == lcount) {
*W_OPEN = 0x70;
wputs(" End of file ");
*W_OPEN = attrs[1];
wcleow();
break; } }
/* Get and process command character */
command:
switch(x = wgetc()) {
case _KUA : /* Backup one line */
--line;
goto display;
case _KDA : /* Advance one line */
++line;
goto display;
case _KPU : /* Backup one page */
line -= 23;
goto display;
case _KPD : /* Advance one page */
line += 23;
goto display;
case _CPU : /* Go to start of file */
line = 0;
goto display;
case _CPD : /* Go to end of file */
line = 32767;
goto display;
case _KRA : /* Advance one column */
++offset;
goto display;
case _KLA : /* Backup one column */
--offset;
goto display;
case _KEN : /* Advance 20 columns */
offset += 20;
goto display;
case _KHO : /* Backup 20 columns */
offset -= 20;
goto display;
case _CHO : /* Reset to 1st column */
offset = 0;
goto display;
case _K1 : /* Display Fkey help */
w_clwin(mwin);
w_puts("1:Help 2:Goto 3:Search 4:Again 5:Gotag 6:Setag 7:Tabsize 8:Colors 9:File 10:Pick", mwin);
goto command;
case _K2 : /* Goto line number */
x = line+1;
if(!wform(20, 10, attrs[2], form3, &x))
line = x - 1;
goto display;
case _K3 : /* Initial Search */
if(!wform(7, 10, attrs[2], form4, search_string[file])
&& search(search_string[file], line))
goto display;
goto command;
case _K4 : /* Repeat Search */
if(search(search_string[file], line+1))
goto display;
goto command;
case _K5 : /* Move to tag */
if((!tag_menu(15, 8)) && tags[tag])
line = tags[tag] - 1;
goto display;
case _K6 : /* Set tag */
if(!tag_menu(55, 8))
tags[tag] = line + 1;
goto command;
case _K7 : /* Set TAB size */
x = tab_size;
if(!wform(20, 10, attrs[2], form2, &x))
tab_size = x ? x : 1;
goto display;
case _K8 :
colors();
goto display;
case _K9 : /* Browse another file */
*buffer = 0;
if(!wform(7, 10, attrs[2], form1, buffer)) {
save_info();
if(open_file(buffer)) {
strcpy(filename[file = fnext++ % NUM_FILES], buffer);
goto display; } }
goto command;
case _K10 : /* Pick a previously opened file */
for(i=Msel=x=0; i < NUM_FILES; ++i) {
if(*filename[i]) {
if(i == file)
Msel = x;
Mptr[x] = filename[i];
Mval[x++] = i; } }
Mptr[x] = 0;
if(!wmenu(15, 8, attrs[2], Mptr, &Msel)) {
save_info();
if(open_file(filename[Msel])) {
file = Msel;
restore_info();
goto display; } }
goto command;
case 0x1B : /* exit */
save_info();
fclose(fp);
wclose();
wclose();
return; }
/* Command key not recognized... */
wputc(7);
goto command;
}
/*
* Open and index a file
*/
open_file(name)
char *name;
{
int c;
/* Attempt to open the file - report if failure */
if(!(c = fopen(name, "rb"))) {
w_clwin(mwin);
w_printf(mwin,"Unable to access: '%s'", name);
return 0; }
w_clwin(mwin);
w_printf(mwin,"Indexing '%s'...", name);
/* Close previously open file (if any) */
if(fp)
fclose(fp);
fp = c;
/* Reset viewer file control variables */
sizeh = sizel = maxline = lcount = line = offset = tag = 0;
for(c=0; c < NUM_TAGS; ++c)
tags[c] = 0;
/* Build table of line numbers .vs. file offsets */
while((c = getc(fp)) != EOF) {
if(!++sizel)
++sizeh;
if(c == '\n') {
/* if(!++sizel)
++sizeh; */
if(!(++lcount & 0x1F)) {
lines[maxline][0] = sizel;
lines[maxline++][1] = sizeh; } } }
return -1;
}
/*
* Display status in the message window
*/
update_status()
{
w_gotoxy(0, 0, mwin);
w_printf(mwin,"%-50s Line: %u of %u, Col: %u", filename[file], line+1, lcount, offset+1);
w_cleow(mwin);
}
/*
* Position file to line 'n'
*/
gotoline(line)
unsigned line;
{
int c, i;
rewind(fp);
/* If more than 32 lines... seek to it */
if(i = line >> 5) {
--i;
fseek(fp, lines[i][1], lines[i][0], 0); }
/* Read till we get to exact line */
i = line & 0x1F;
while(i) {
if((c = getc(fp)) == EOF)
return -1;
if(c == '\n')
--i; }
return 0;
}
/*
* Display a line with tabs expanded
*/
display_line(text)
char *text;
{
int p, o;
unsigned char c;
o = offset + SCREEN_SIZE;
p = 0;
while((c = *text++) && (p < o)) {
if(c == '\t') { /* tab */
do
if(p >= offset)
wputc(' ');
while(++p % tab_size); }
else if(c != '\r') { /* not a tab */
if(++p > offset) {
if(c < ' ') { /* Control character */
*W_OPEN = 0x70;
wputc(c + 0x40);
*W_OPEN = attrs[1];
continue; }
wputc((c <= '~') ? c : 0xFE); } } }
if(p < o)
wcleol();
}
/*
* Search for string in file
*/
search(string, l)
char *string;
int l;
{
char buffer[LINE_SIZE+1];
w_clwin(mwin);
w_printf(mwin, "Searching from line %u for '%s'... ", l+1, string);
gotoline(l);
while(fgets(buffer, sizeof(buffer)-1, fp)) {
if(inline(buffer, string)) {
line = l;
return -1; }
++l; }
w_printf(mwin, "Not found!", string);
return 0;
}
/*
* Test for string occuring within a line.
* We could easily do this in 'C', however its a good chance to show
* off inline assembly language, and get a slight speed improvement.
*/
inline(line, string) asm
{
MOV SI,6[BP] ; Get line
inl1: MOV DI,4[BP] ; Get string
inl2: MOV AL,[DI] ; Get char from string
MOV AH,[SI] ; Get char from line
AND AL,AL ; End of string?
JZ inl3 ; Yes, we have match
INC SI ; Advance line
INC DI ; Advance string
CMP AL,AH ; *line == *string?
JZ inl2 ; Yes, keep looking
AND AH,AH ; End of string?
JNZ inl1 ; No, keep trying
; End of line... string was not found
XOR AX,AX ; 0 = Not found
JMP SHORT inl4 ; And exit
; Found string
inl3: MOV AX,-1 ; 1 = Success
inl4:
}
/*
* Save viewer information for current file.
*/
save_info()
{
int i, *ptr;
ptr = file_info[file];
*ptr = line;
*++ptr = offset;
*++ptr = tab_size;
*++ptr = tag;
for(i=0; i < NUM_TAGS; ++i)
*++ptr = tags[i];
}
/*
* Reload viewer information for current file.
*/
restore_info()
{
int i, *ptr;
ptr = file_info[file];
line = *ptr;
offset = *++ptr;
tab_size = *++ptr;
tag = *++ptr;
for(i=0; i < NUM_TAGS; ++i)
tags[i] = *++ptr;
}
/*
* Build and perform a menu of tag line numbers.
*/
tag_menu(x, y)
int x, y;
{
int i;
char *tagnames[NUM_TAGS+1], text[NUM_TAGS][6];
for(i=0; i < NUM_TAGS; ++i) {
if(tags[i])
sprintf(tagnames[i] = text[i], "%u", tags[i]);
else
tagnames[i] = "-----"; }
tagnames[NUM_TAGS] = 0;
return wmenu(x, y, attrs[2], tagnames, &tag);
}
/*
* Set window colors
*/
colors()
{
int num, color, f, b;
static char *cnames[] = {
"Message line",
"Main screen",
"Pop up windows" };
num = 0;
for(;;) {
color = attrs[num];
f = color & 0x0F;
b = color & 0xF0;
wopen(20, 9, 32, 7, (WSAVE|WCOPEN|WBOX2)|(color & 0xFF));
wcursor_off();
*W_OPEN = (f << 4) | (b >> 4);
wputs(cnames[num]);
*W_OPEN = color;
wputs("\n\nUp/Down = Change forground\n");
wputs("Left/Right = Change background\n");
wputs("PgUp/PgDn = Change screen");
switch(wgetc()) {
case 0x1B :
wclose();
*mwin = attrs[0];
*W_OPEN = attrs[1];
return;
case _KPU : num = (num + 1) % 3; break;
case _KPD : num = (num + 2) % 3; break;
case _KUA : ++f; goto setcolor;
case _KDA : --f; goto setcolor;
case _KRA : b += 16; goto setcolor;
case _KLA : b -= 16;
setcolor:
attrs[num] = (color & 0xFF00) | (f & 0x0f) | (b & 0xF0);
default: }
wclose(); }
}
/*
* Main program - parse arguments, and start browser (if not TSR).
*/
main(argc, argv)
int argc;
char *argv[];
{
int i;
/* At startup, zero filenames & search strings */
for(i=0; i < NUM_FILES; ++i)
*filename[i] = *search_string[i] = 0;
/* If not TSR, activate browser now */
if((argc < 2) || (*(argptr = argv[1]) != '/')) {
browser();
return; }
/* TSR... parse hotkeys & set TSR vectors */
i = 0;
while(*++argptr) switch(toupper(*argptr)) {
case 'A' : i |= ALT; break;
case 'C' : i |= CONTROL; break;
case 'L' : i |= L_SHIFT; break;
case 'R' : i |= R_SHIFT; break;
case 'S' : i |= SYS_REQ; break;
default: abort("\nInvalid HOTKEY"); }
argptr = (argc > 2) ? argv[2] : 0;
tsr(&browser, i, 10000);
}